/**
 * SpringContext.java
 * com.sitech.ismp.workflow.server
 *
 * Function： TODO
 *
 *   ver     date      		author
 * ──────────────────────────────────
 *   		 Jun 25, 2010 		geutopia
 *
 * Copyright (c) 2010, TNT All Rights Reserved.
 */

package com.sitech.context;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.ServletContext;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * ClassName:SpringContext
 * Function: TODO ADD FUNCTION
 * Reason:	 TODO ADD REASON
 *
 * @author   geutopia
 * @version
 * @since    Ver 1.1
 * @Date	 Jun 25, 2010		3:23:40 PM
 *
 * @see
 */
public final class SpringContext
{

    private static BeanFactory springBeanFactory = null;
    private static final Lock lock = new ReentrantLock();
    private static final Condition notNull = lock.newCondition();

	public synchronized static boolean initialize(ServletContext servletContext)
	{
        ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext);
        springBeanFactory = (BeanFactory) context;
        System.out.println("SpringContext initialized!");
        signalAll();
        return true;
    }

    public static Object getBean(String beanName) 
    {
        return getBeanFactory().getBean(beanName);
    }

    public static List<Object> getObject(Class objectClass)
    {
        List<Object> list = new ArrayList<Object>();
        BeanFactory beanFactory = getBeanFactory();

        if (beanFactory instanceof ListableBeanFactory) 
        {
            ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
            Map<String, Object> map = listableBeanFactory.getBeansOfType(objectClass);
            if (map != null && map.size() > 0) 
            {
                for (Map.Entry<String, Object> entry : map.entrySet())
                {
                    list.add(entry.getValue());
                }
            }
        } 
        else 
        {
            Object object = beanFactory.getBean(objectClass.getName());
            list.add(object);
        }
        return list;
    }

	public static void setBeanFactory(BeanFactory beanFactory)
	{
        springBeanFactory = beanFactory;
        signalAll();
    }

    /**
     * 在获取到BeanFactory之前等待，直到初始化完成或者等待超过100秒
     * @author liujhc
     * @date 2012-07-09 13:38:42
     * @return
     */
    private static BeanFactory getBeanFactory() {
        if (springBeanFactory == null) {
            lock.lock();
            try {
                System.out.println("Waiting for SpringContext to initialize...");
                notNull.await(100, TimeUnit.SECONDS);//在springBeanFactory为null时等待，直到被唤醒（notNull.signal()）或者超过100秒自动醒来
                System.out.println("No longer wait for SpringContext!");
                if (springBeanFactory == null) {
                    throw new RuntimeException("没有初始化BeanFactory！");
                }
            } catch (InterruptedException e) {
                throw new RuntimeException("没有初始化BeanFactory！", e);
            } finally {
                lock.unlock();
            }
        }
        return springBeanFactory;
    }

    private static void signalAll() {
        lock.lock();
        try {
            notNull.signalAll();//springBeanFactory notNull 条件满足，唤醒所有等待此条件的线程
        } finally {
            lock.unlock();
        }
    }
}
